package com.kdtech.rpc;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;

/**
 * 远程调用客户端管理
 * 使用方法:
 * 	new RPCServer(xxx,xxx...).start()
 * 
 * 停止服务：
 *  server.stop();
 *  
 * 
 *  
 * @author KK
 *
 * @param <T>
 */
public class RPCClient<T> {
	/**
	 * 接口
	 */
	private Class<T> interfaceClass;		
	private int portNo;
	private String serviceName;
	private int connections = 1;
	private int timeout = 15000;//超时默认15秒
	private String ipAddress;
	private T client;
	/**
	 * @param interfaceClass	接口class
	 * @param implClass	服务实现class
	 * @param portNo	端口
	 * @param serviceName	服务名称
	 */
	public RPCClient(Class<T> interfaceClass,String ipAddress,int portNo) {
		super();
		this.interfaceClass = interfaceClass;
		this.ipAddress = ipAddress;
		this.portNo = portNo;
	}

	/**
	 * 获取RPC客户端
	 * @return	客户端对象
	 * @throws Exception
	 */
	public T getClient() throws Exception{
		if (client==null){
			synchronized (this) {
				if (client==null){
					// 当前应用配置
					ApplicationConfig application = new ApplicationConfig();
					application.setName(interfaceClass.getSimpleName() + "_client_stub");
					 
					// 连接注册中心配置
//					RegistryConfig registry = new RegistryConfig();
//					registry.setAddress("10.20.130.230:9090");
//					registry.setUsername("aaa");
//					registry.setPassword("bbb");
					 
					// 注意：ReferenceConfig为重对象，内部封装了与注册中心的连接，以及与服务提供方的连接
					 
					// 引用远程服务
					ReferenceConfig<T> reference = new ReferenceConfig<T>(); // 此实例很重，封装了与注册中心的连接以及与提供者的连接，请自行缓存，否则可能造成内存和连接泄漏
					reference.setApplication(application);
//					reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
					reference.setInterface(interfaceClass);
					// 如果点对点直连，可以用reference.setUrl()指定目标地址，设置url后将绕过注册中心，
					// 其中，协议对应provider.setProtocol()的值，端口对应provider.setPort()的值，
					// 路径对应service.setPath()的值，如果未设置path，缺省path为接口名
					reference.setUrl("dubbo://"+ipAddress+":" + portNo); 
					reference.setActives(100);
					reference.setConnections(connections);
					reference.setTimeout(timeout);
					// 和本地bean一样使用xxxService
					// 注意：此代理对象内部封装了所有通讯细节，对象较重，请缓存复用
					client = reference.get();
				}
			}
		}
		return client;
		
	}
	
	
	
	
	public Class<T> getInterfaceClass() {
		return interfaceClass;
	}

	public void setInterfaceClass(Class<T> interfaceClass) {
		this.interfaceClass = interfaceClass;
	}


	public int getPortNo() {
		return portNo;
	}

	public void setPortNo(int portNo) {
		this.portNo = portNo;
	}

	public String getServiceName() {
		return serviceName;
	}

	public void setServiceName(String serviceName) {
		this.serviceName = serviceName;
	}


	public int getTimeout() {
		return timeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}


	public static void main(String[] args) {
		
	}

}
